package mk.jug.academy.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import mk.jug.academy.model.Lecturer;
import mk.jug.academy.model.Page;
import mk.jug.academy.model.status.LecturerStatus;

import org.springframework.stereotype.Repository;


/**
 * DAO for the {@link Lecturer} domain model.
 *
 * @author Ice.Penov
 */
@Repository
public class LecturerDAO extends GenericDAO<Lecturer> {
	
	/**
	 * Fetches the lecturers, regardless of their status, in a paged manner, 
	 * considering the start/end boundaries. 
	 */
	public Page<Lecturer> findAll(final int start, final int end) {
		return new QueryEMContext<Page<Lecturer>>() {
			@Override @SuppressWarnings("unchecked")
			public Page<Lecturer> query(EntityManager em) {
				Query query = em.createQuery("Select from mk.jug.academy.model.Lecturer l order by l.rating desc");
				query.setFirstResult(start);
				query.setMaxResults(end);
				List<Lecturer> list = query.getResultList();
				query = em.createQuery("Select count(l.id) from Lecturer l");
				return new Page<Lecturer>(initialize(list), (Integer) query.getSingleResult());
			}
		}.result();
	}
				
	/**
	 * Fetches the lecturers, given their status, in a paged manner, 
	 * considering the start/end boundaries. 
	 */
	public Page<Lecturer> findByStatus(final LecturerStatus status, final int start, final int end, final String orderBy) {
		return new QueryEMContext<Page<Lecturer>>() {
			@Override @SuppressWarnings("unchecked")
			public Page<Lecturer> query(EntityManager em) {
				Query query = em.createQuery("Select l from mk.jug.academy.model.Lecturer l where l.status = :status order by l." + orderBy + " desc");
				query.setParameter("status", status);
				query.setFirstResult(start);
				query.setMaxResults(end);
				List<Lecturer> list = query.getResultList();
				query = em.createQuery("Select count(l.id) from mk.jug.academy.model.Lecturer l where l.status = :status");
				query.setParameter("status", status);
				return new Page<Lecturer>(initialize(list), (Integer) query.getSingleResult());
			}
		}.result();
	}
	
	/**
	 * Fetches the lecturers, given the status, as a list, 
	 * considering orderBy property. 
	 */	
	public List<Lecturer> findByStatus(final LecturerStatus status, final String orderBy) {
		return new QueryEMContext<List<Lecturer>>() {
			@Override @SuppressWarnings("unchecked")
			public List<Lecturer> query(EntityManager em) {
				Query query = em.createQuery("Select l from mk.jug.academy.model.Lecturer l where l.status = :status order by l." + orderBy + " desc");
				query.setParameter("status", status);
				return initialize(query.getResultList());
			}
		}.result();
	}	
	
	/**
	 * Fetch the ACTIVE lecturer, with the supplied email.
	 */
	public Lecturer findActiveByEmail(final String email) {
		return new QueryEMContext<Lecturer>() {
			@Override
			public Lecturer query(EntityManager em) {
				Query query = em.createQuery("Select from mk.jug.academy.model.Lecturer l where l.email = :email and l.status = :status");
				query.setParameter("email", email);
				query.setParameter("status", LecturerStatus.ACTIVE);
				return (Lecturer) query.getSingleResult();
			}
		}.result();
	}
	
	/**
	 * Fetch ANY lecturer, with the supplied email.
	 */
	public Lecturer findAnyByEmail(final String email) {
		return new QueryEMContext<Lecturer>() {
			@Override
			public Lecturer query(EntityManager em) {
				Query query = em.createQuery("Select from mk.jug.academy.model.Lecturer l where l.email = :email");
				query.setParameter("email", email);
				return (Lecturer) query.getSingleResult();
			}
		}.result();
	}

}